﻿namespace OpenPms.Services;

public partial class OrderService
{
    #region 查询房价和房量

    public async Task<List<VPriceQuantity>> QueryPriceQuantityAsync(int hotelId, Guid rateId, DateOnly dateStart, DateOnly dateEnd, Guid? roomTypeId)
    {
        var items = await QueryQuantityAsync(hotelId, dateStart, dateEnd, roomTypeId);
        var retItems = await QueryPriceAsync(items, rateId, dateStart, dateEnd);

        if (await db.Rates.AnyAsync(ii => ii.Id == rateId && ii.HotelId == hotelId && ii.RateType == ERateType.钟点房))
            retItems.RemoveAll(ii => ii.Prices.Any(jj => jj.DelayPrice is null || jj.Price == 0));
        return retItems;
    }

    #endregion

    #region 查询房量
    public async Task<List<VPriceQuantity>> QueryQuantityAsync(int hotelId, DateOnly dateStart, DateOnly dateEnd, Guid? roomTypeId)
    {
        IQueryable<TRoomType> outter;
        IQueryable<TQuantity> inner;
        if (roomTypeId is null)
        {
            outter = db.RoomTypes.Where(ii => ii.HotelId == hotelId);
            inner = db.Quantities.Where(ii => ii.HotelId == hotelId && ii.Date >= dateStart && ii.Date <= dateEnd);

        }
        else
        {
            outter = db.RoomTypes.Where(ii => ii.Id == roomTypeId);
            inner = db.Quantities.Where(ii => ii.RoomTypeId == roomTypeId && ii.HotelId == hotelId && ii.Date >= dateStart && ii.Date <= dateEnd);
        }
        var items = await outter.GroupJoin(inner, ii => ii.Id, ii => ii.RoomTypeId,
                (rt, qtys) => new { rt.Id, rt.Name, rt.Quantity, MaxQty = qtys.Select(ii => ii.Quantity).DefaultIfEmpty().Max() }).ToListAsync();
        return await outter.GroupJoin(inner, ii => ii.Id, ii => ii.RoomTypeId,
             (rt, qtys) => new VPriceQuantity(rt.Id, rt.Name, rt.Quantity - qtys.Select(ii => ii.Quantity).DefaultIfEmpty().Max())).ToListAsync();

    }

    #endregion

    #region 查询房价
    //public async Task<List<VPriceQuantity>> QueryPriceAsync(int hotelId, Guid rateId, DateOnly dateStart, DateOnly dateEnd, Guid? roomTypeId)
    //{
    //    var query = from x in db.RoomTypes select x;
    //    if (roomTypeId is null)
    //        query = query.Where(ii => ii.HotelId == hotelId);
    //    else
    //        query = query.Where(ii => ii.HotelId == hotelId && ii.Id == roomTypeId);

    //    var items = await query.Select(ii => new VPriceQuantity(ii.Id, ii.Name)).ToListAsync();

    //    return await QueryPriceAsync(items, rateId, dateStart, dateEnd);
    //}

    private async Task<List<VPriceQuantity>> QueryPriceAsync(List<VPriceQuantity> items, Guid rateId, DateOnly dateStart, DateOnly dateEnd)
    {

        List<TPrice> priceItems = new List<TPrice>();
        DateOnly? maxDate = null;


        for (var day = dateStart; day <= dateEnd; day = day.AddDays(1))
        {
            if (maxDate is null || maxDate < day)
            {
                maxDate = await db.Prices.Where(ii => ii.RateId == rateId && ii.Date >= day).Select(ii => ii.Date).FirstOrDefaultAsync();
                if (maxDate is null)
                    return new();
                var roomTypeIds = items.Select(ii => ii.RoomTypeId).ToList();
                priceItems = await db.Prices.Where(ii => ii.RateId == rateId && ii.Date == maxDate && roomTypeIds.Contains(ii.RoomTypeId)).ToListAsync();
            }
            for (int i = items.Count - 1; i >= 0; i--)
            {
                var item = items[i];
                var p = priceItems.FirstOrDefault(ii => ii.RoomTypeId == item.RoomTypeId)?.GetPrice(day);
                if (p is null || p.Price == 0)
                {
                    items.Remove(item);
                    continue;
                }
                item.Prices.Add(p);
            }
            if (items.Count == 0)
                return items;
        }
        return items;

    }

    #endregion


}
